package eval.engine.cplex;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import eval.exceptions.CplexMapIndexToVmIdException;
import eval.vm.VMIdentifier;
import eval.vm.VirtualMachine;

public class CplexMapIndexToVmId {
	
	
	private Map<VMIdentifier,Integer> vmIdToCplexIndex;
	private VMIdentifier[] cplexIndexToVmId;
	
	public CplexMapIndexToVmId () {
		cplexIndexToVmId = new VMIdentifier[0];
		vmIdToCplexIndex = new HashMap<VMIdentifier, Integer>();
	}
	
	public CplexMapIndexToVmId (List<VirtualMachine> vmsToIdentify ) {
		cplexIndexToVmId = new VMIdentifier[vmsToIdentify.size()];
		vmIdToCplexIndex = new HashMap<VMIdentifier, Integer>();
		int cplexId = 0;
		
		for(VirtualMachine vm : vmsToIdentify) {
			vmIdToCplexIndex.put(vm.getIdentifier(), cplexId);
			cplexIndexToVmId[cplexId] = vm.getIdentifier();
			cplexId++;
		}
	}
	
	public CplexMapIndexToVmId(CplexMapIndexToVmId other) {
		VMIdentifier[] tmp  = other.getCplexIndexToVmId();
		this.vmIdToCplexIndex = new HashMap<VMIdentifier, Integer>();
		this.cplexIndexToVmId = new VMIdentifier[tmp.length];
		for(int i=0; i<tmp.length; i++) {
			this.cplexIndexToVmId[i] = tmp[i];
			this.vmIdToCplexIndex.put(cplexIndexToVmId[i], i);
		}
	}
	
	public Map<VMIdentifier, Integer> getVmIdToCplexIndex() {
		return vmIdToCplexIndex;
	}

	public VMIdentifier[] getCplexIndexToVmId() {
		return cplexIndexToVmId;
	}
	
	public VMIdentifier getVmIdFromCplexIndex(int cplexIndex) throws CplexMapIndexToVmIdException {
		if(cplexIndexToVmId.length<=cplexIndex)
			throw new CplexMapIndexToVmIdException("Vm not found");
		return cplexIndexToVmId[cplexIndex];
	}
	
	public int getCplexIndexFromVmId(VMIdentifier vmId) throws CplexMapIndexToVmIdException {
		if(!vmIdToCplexIndex.containsKey(vmId))
			throw new CplexMapIndexToVmIdException("Vm not found");
		return vmIdToCplexIndex.get(vmId);
	}
	
	public void removeVmAtList(List<VirtualMachine> vmToRemove) {
		VMIdentifier[] tmp = new VMIdentifier[cplexIndexToVmId.length-vmToRemove.size()];
		List<VMIdentifier> vmIdList = new ArrayList<VMIdentifier>();
		for(VirtualMachine vm :vmToRemove)
			vmIdList.add(vm.getIdentifier());
		int cplexId=0;
		for(VMIdentifier id :cplexIndexToVmId) {
			if(!vmIdList.contains(id)) {
				tmp[cplexId] = id;
				cplexId++;
			} else {
				vmIdToCplexIndex.remove(id);
			}
		}
		cplexIndexToVmId = tmp;
	}
	
	public void addVmAtList(List<VirtualMachine> vmToAdd) {
		VMIdentifier[] tmp = new VMIdentifier[cplexIndexToVmId.length+vmToAdd.size()];
		int cplexId = 0;
		for(VMIdentifier id :cplexIndexToVmId) {
			tmp[cplexId] = id;
			cplexId++;
		}
		for(VirtualMachine vm :vmToAdd) {
			tmp[cplexId] = vm.getIdentifier();
			vmIdToCplexIndex.put(vm.getIdentifier(), cplexId);
			cplexId++;
		}
		cplexIndexToVmId = tmp;
	}
	
	public Map<VMIdentifier,int[]> getChangesAtCplexIdFrom(CplexMapIndexToVmId other) {
		Map<VMIdentifier,int[]> toRet = new HashMap<VMIdentifier,int[]>();
		for(Map.Entry<VMIdentifier, Integer> thisVmIdToCplex : this.vmIdToCplexIndex.entrySet()) {
			toRet.put(thisVmIdToCplex.getKey(), new int[2]);
			toRet.get(thisVmIdToCplex.getKey())[0] = thisVmIdToCplex.getValue();
			toRet.get(thisVmIdToCplex.getKey())[1] = -1;
		}
		for(Map.Entry<VMIdentifier, Integer> otherVmIdToCplex : other.getVmIdToCplexIndex().entrySet()) {
			if(toRet.containsKey(otherVmIdToCplex.getKey()))
				toRet.get(otherVmIdToCplex.getKey())[1] = otherVmIdToCplex.getValue();
			else {
				toRet.put(otherVmIdToCplex.getKey(), new int[2]);
				toRet.get(otherVmIdToCplex.getKey())[0] = -1;
				toRet.get(otherVmIdToCplex.getKey())[1] = otherVmIdToCplex.getValue();
			}
		}
		
		return toRet;
	}
	
	public boolean isVmAtMap(VMIdentifier vmId) {
		return vmIdToCplexIndex.containsKey(vmId);
	}
}














